
import re
import json
from bs4 import BeautifulSoup
import psycopg2
import pdb
__DEBUG__ = True

__db_name__ = 'dev_database'
__db_role__ = 'anglenet'

        
class Util:
    SLEEP_SECONDS = 1 
    @staticmethod
    def timeToInt(t):
        return int(t.strip().replace('-','').replace(':', '').replace(' ', ''))

    @staticmethod
    def delay(timeout):
        def delayDecorator(func):
            def funcWrapper(*args, **kwargs):
                time.sleep(timeout)
                func(*args, **kwargs)
            return funcWrapper
        return delayDecorator

class HtmlUtils:
    HEADERS = {
        "Host": "weibo.com",
        "Connection": "keep-alive",
        "Upgrade-Insecure-Requests": '1',
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "DNT": '1',
        "Accept-Encoding": "gzip, deflate, sdch",
        "Accept-Language": "en-US,en;q=0.8",
        "Cookie": "SUB=_2A251QGgtDeTxGeNJ6FoU8i_FzD2IHXVWNN7lrDV8PUNbmtBeLVnYkW8c7PBO_ybRJA87hv2zElQDm7fzvQ.."
    }

    @staticmethod
    def findScript(html, domid):
        """
        Find named script tag
        """
        domid = '"domid":"' + domid 
        for script in BeautifulSoup(html, 'lxml').find_all('script'):
            script = str(script)
            if domid  in script:
                break
        return HtmlUtils._scriptToHtml(script)

    @staticmethod
    def findScriptWithDomid(html, domid_name):
        """
        Find named script tag and the feed number
        """
        domid = '"domid":"' + domid_name 
        for script in BeautifulSoup(html, 'lxml').find_all('script'):
            script = str(script)
            if domid  in script:
                break
        return HtmlUtils._scriptToHtmlWithDomid(script)
    @staticmethod
    def loadJsonResponse(response, key):
        """
        Retrieve key from reponse
        """
        response = response.replace('\\t', '').replace('\\n', '').replace('\\r', '')
        response = json.loads(response)
        if key in response.keys():
            return response[key]
        return None


    @staticmethod
    def _scriptToHtmlWithDomid(script):
        """
        Extract html part from sina script
        """
        script = script.replace('\\t', '').replace('\\n', '').replace('\\r', '')
        script = re.sub(r'\\', '', script)
        if "FM.view" in script:
            index = script.find('domid') + 8
            domid = script[index: script.find('"', index)]
            index = script.find('html')
            if index < 0:
                print("html part is missing in this script")
                return (None, domid)
            else:
                html = script[index+8: -12]
                return (html, domid)
        else:
            print('Input does not seem to be a line of javascript')
            print(script)
            return (None, None)


    @staticmethod
    def _scriptToHtml(script):
        """
        Extract html part from sina script
        """
        script = script.replace('\\t', '').replace('\\n', '').replace('\\r', '')
        script = re.sub(r'\\', '', script)
        if "FM.view" in script:
            index = script.find('domid') + 8
            domid = script[index: script.find('"', index)]
            index = script.find('html')
            if index < 0:
                print("html part is missing in this script")
                return None
            else:
                html = script[index+8: -12]
                return html
        else:
            print('Input does not seem to be a line of javascript')
            print(script)
            return None
class DBUtils:
    @staticmethod
    def initdb():
        return DBUtils._initdb(__db_name__, __db_role__)

    @staticmethod
    def _initdb(db_name, user_name):
        return psycopg2.connect("dbname=" + db_name + " user=" + user_name + " host='/var/run/postgresql/'") 

    @staticmethod
    def dumpUserInfo(users):
        """
        Dump user information to database
        """
        global __db_name__, __db_role__
        db_con = DBUtils.initdb();
        cur = db_con.cursor()
        for user in users:
            print(user)
            cur.execute("""insert into users (uid, link, page_id, domain, 
                    nick_name, num_followees, num_fans, num_microblogs, overview, 
                    tags, gender, register_time) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);""", \
                    (user.uid, user.link, user.config.page_id,\
                     user.config.domain, user.nick_name, \
                     user.num_followees, user.num_fans, user.num_microblogs,\
                     user.overview, user.tags, user.gender, user.register_time)) 
        cur.close()
        db_con.commit()
        db_con.close()

    @staticmethod
    def loadUserConfig():
        """
        Return an array of user configs.
        """
        db_con = DBUtils.initdb();
        cur = db_con.cursor()
        configs = []
        cur.execute("""select uid, page_id, domain from users;""")
        for item in cur.fetchall():
            conf = PageConfigInfo()
            conf.uid = item[0]
            conf.page_id = item[1]
            conf.domain = item[2]
            configs.append(conf)
        return configs
    @staticmethod
    def dumpUserReposts(reposts, db_con):
        """
        Persist the reposts to table user_reposts
        """
        cur = db_con.cursor()
        for repost in reposts:
            cur.execute("""insert into user_reposts (last_uid, last_pid,
                    last_domain, uid, content, time, original_time) values (%s,
                    %s, %s, %s, %s, %s, %s);""", (repost.last_uid,
                    repost.last_pid, repost.last_domain,
                    repost.uid, repost.content, repost.time, repost.original_time))
        cur.close()
        db_con.commit()

    @staticmethod
    def dumpUserPosts(posts, db_con):
        """
        Persist the posts to table user_posts 
        """
        cur = db_con.cursor()
        for post in posts:
            cur.execute("""insert into user_posts (uid, content, time)
                    values (%s, %s, %s);""", (post.uid, post.content, post.time))
        cur.close()
        db_con.commit()
    @staticmethod
    def dumpTrtopicOverview(topics,db_con):
        """
        Persist the topic overviews to table topics
        """
        cur = db_con.cursor()
        for tid, content in topics.items():
            cur.execute("""update topics set overview = %s where tid = %s;""",
                    (tid, content))
        cur.close()
        db_con.commit()
    def loadTrtopicLinks(db_con):
        """
        Load topic links from table topics
        """
        topics = dict()
        cur = db_con.cursor()
        cursor.execute("""select id, link from topics;""")
        for record in cursor.fetchall():
            topics[record[0]] = record[1]
        cursor.close()
        return topics





class PageConfigInfo:
    def __init__(self):
        self.uid = 0
        self.page_id = 0
        self.domain = 0
    def __str__(self):
        return "UID: {}, Page_id: {}, Domain: {}".format(
                self.uid, self.page_id, self.domain)
class UserInfo:
    def __init__(self):
        self.uid = 0
        self.link = ""
        self.nick_name = ''
        self.num_followees = 0
        self.num_fans = 0
        self.num_microblogs = 0
        #Personal information
        self.overview = ''
        self.tags = ''          
        self.gender = ''
        self.register_time = '' 
        self.config = None
    def __str__(self):
        return "UID: {}, Link: {}, Nick name: {}, Gender:{}, RegisterTime:{}\nFollowees:{}, Fans:{}, Microblogs:{}\nOverview:{}\nTags:{}\nConfig:{}\n".format(
                self.uid, self.link, self.nick_name, self.gender, self.register_time, 
                self.num_followees, self.num_fans, self.num_microblogs, 
                self.overview, self.tags, self.config)
class Repost:
    """
    Represents a single repost of the form
    <last_uid, last_pid, last_domain, uid, content, time>
    """
    def __init__(self):
        self.last_uid = 0
        self.last_pid = 0 
        self.last_domain = 0
        self.uid = 0
        self.content = ''
        self.time = ''
        self.original_time = ''
    def __str__(self):
        return "(Repost)<" + str(self.last_uid) + ", " + str(self.last_pid) + ", " + \
                str(self.last_domain) + ", " + str(self.uid) + ", " + self.content + ", " + \
                self.time + ', ' + self.original_time + ">"

class Post:
    """
    Represents a single weibo of the form
    <uid, content, time>
    """
    def __init__(self):
        self.uid = 0
        self.content = ''
        self.time = ''
    def __str__(self):
        return "(Post)<" + str(self.uid) + ", " + self.content + ", " + self.time + ">"

class WeiboSample:
    """
    Represents a single weibo sample
    <last_uid, uid, content, time>
    """
    def __init__(self):
        self.last_uid = 0
        self.uid = 0
        self.content = ''
        self.time = ''
    
    def __str__(self):
        return '<' + str(self.last_uid) + ', ' + str(self.uid) + ', ' +\
                self.content + ', ' + self.time + '>';
          



